<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>JVM内存结构 | Kehao&#39;s blog</title>
    <meta name="generator" content="VuePress 1.9.5">
    <link rel="icon" href="/img/logo.png">
    <meta name="description" content="人生如逆旅,我亦是行人">
    <meta name="keywords" content="个人技术博客,技术文档,学习,github,markdown">
    <meta name="theme-color" content="#11a8cd">
    
    <link rel="preload" href="/assets/css/0.styles.d732307f.css" as="style"><link rel="preload" href="/assets/js/app.28ae8733.js" as="script"><link rel="preload" href="/assets/js/2.89335391.js" as="script"><link rel="preload" href="/assets/js/5.0ce40fe9.js" as="script"><link rel="prefetch" href="/assets/js/10.240396ac.js"><link rel="prefetch" href="/assets/js/100.b46b3d4a.js"><link rel="prefetch" href="/assets/js/101.10d51f47.js"><link rel="prefetch" href="/assets/js/102.8375579c.js"><link rel="prefetch" href="/assets/js/103.797ca064.js"><link rel="prefetch" href="/assets/js/104.7ac1dbd0.js"><link rel="prefetch" href="/assets/js/105.7fe709e0.js"><link rel="prefetch" href="/assets/js/106.40e4b399.js"><link rel="prefetch" href="/assets/js/107.bccbf8bb.js"><link rel="prefetch" href="/assets/js/108.3ed7aba6.js"><link rel="prefetch" href="/assets/js/109.a0e93f14.js"><link rel="prefetch" href="/assets/js/11.4bac35ef.js"><link rel="prefetch" href="/assets/js/110.c80cce70.js"><link rel="prefetch" href="/assets/js/111.023f84fc.js"><link rel="prefetch" href="/assets/js/112.d3a4a276.js"><link rel="prefetch" href="/assets/js/113.31392123.js"><link rel="prefetch" href="/assets/js/114.af8c76ba.js"><link rel="prefetch" href="/assets/js/115.3ce4813c.js"><link rel="prefetch" href="/assets/js/116.15c681c0.js"><link rel="prefetch" href="/assets/js/117.54980b1e.js"><link rel="prefetch" href="/assets/js/118.3444c215.js"><link rel="prefetch" href="/assets/js/119.c98d3229.js"><link rel="prefetch" href="/assets/js/12.050d707f.js"><link rel="prefetch" href="/assets/js/120.083cde85.js"><link rel="prefetch" href="/assets/js/121.cd131c59.js"><link rel="prefetch" href="/assets/js/122.f16793cf.js"><link rel="prefetch" href="/assets/js/123.d482f8ed.js"><link rel="prefetch" href="/assets/js/124.e7da2ff5.js"><link rel="prefetch" href="/assets/js/125.ddb5795a.js"><link rel="prefetch" href="/assets/js/126.9216698d.js"><link rel="prefetch" href="/assets/js/127.53db8068.js"><link rel="prefetch" href="/assets/js/128.a705a820.js"><link rel="prefetch" href="/assets/js/129.8191bdea.js"><link rel="prefetch" href="/assets/js/13.177da736.js"><link rel="prefetch" href="/assets/js/130.49925b47.js"><link rel="prefetch" href="/assets/js/131.42eaeaec.js"><link rel="prefetch" href="/assets/js/132.bb8fe728.js"><link rel="prefetch" href="/assets/js/133.2c687e0b.js"><link rel="prefetch" href="/assets/js/134.edc791f9.js"><link rel="prefetch" href="/assets/js/135.413f8c4f.js"><link rel="prefetch" href="/assets/js/136.73623722.js"><link rel="prefetch" href="/assets/js/137.13f54ead.js"><link rel="prefetch" href="/assets/js/138.5d9b0164.js"><link rel="prefetch" href="/assets/js/139.67d40d82.js"><link rel="prefetch" href="/assets/js/14.12ba4700.js"><link rel="prefetch" href="/assets/js/140.9afcee95.js"><link rel="prefetch" href="/assets/js/141.515b85b0.js"><link rel="prefetch" href="/assets/js/142.d0f3de97.js"><link rel="prefetch" href="/assets/js/143.7f4fe09f.js"><link rel="prefetch" href="/assets/js/144.5dc995d2.js"><link rel="prefetch" href="/assets/js/145.19f96c8c.js"><link rel="prefetch" href="/assets/js/146.bf4c7750.js"><link rel="prefetch" href="/assets/js/147.45515397.js"><link rel="prefetch" href="/assets/js/148.d7e7089b.js"><link rel="prefetch" href="/assets/js/149.d875e020.js"><link rel="prefetch" href="/assets/js/15.223e7317.js"><link rel="prefetch" href="/assets/js/150.343471c3.js"><link rel="prefetch" href="/assets/js/151.fec32985.js"><link rel="prefetch" href="/assets/js/152.f4bf1f1c.js"><link rel="prefetch" href="/assets/js/153.5d635e78.js"><link rel="prefetch" href="/assets/js/154.55d79073.js"><link rel="prefetch" href="/assets/js/155.b9007555.js"><link rel="prefetch" href="/assets/js/156.405f2375.js"><link rel="prefetch" href="/assets/js/157.f452ac4d.js"><link rel="prefetch" href="/assets/js/158.5dc6750f.js"><link rel="prefetch" href="/assets/js/159.82213c98.js"><link rel="prefetch" href="/assets/js/16.21112dcc.js"><link rel="prefetch" href="/assets/js/160.4d1ba3c3.js"><link rel="prefetch" href="/assets/js/161.619ccba0.js"><link rel="prefetch" href="/assets/js/162.796dcb7d.js"><link rel="prefetch" href="/assets/js/163.6f9037fc.js"><link rel="prefetch" href="/assets/js/164.577012e4.js"><link rel="prefetch" href="/assets/js/165.7ebd2d3c.js"><link rel="prefetch" href="/assets/js/166.d2a5f150.js"><link rel="prefetch" href="/assets/js/167.9702fc41.js"><link rel="prefetch" href="/assets/js/168.76fd933e.js"><link rel="prefetch" href="/assets/js/169.058c9db2.js"><link rel="prefetch" href="/assets/js/17.55366bc0.js"><link rel="prefetch" href="/assets/js/170.3aaf5ad7.js"><link rel="prefetch" href="/assets/js/171.75566559.js"><link rel="prefetch" href="/assets/js/172.cac21ccf.js"><link rel="prefetch" href="/assets/js/173.d4c9ad5a.js"><link rel="prefetch" href="/assets/js/174.a6b660d1.js"><link rel="prefetch" href="/assets/js/175.856f0cf5.js"><link rel="prefetch" href="/assets/js/176.6e717472.js"><link rel="prefetch" href="/assets/js/177.16f32dda.js"><link rel="prefetch" href="/assets/js/178.3e33e81a.js"><link rel="prefetch" href="/assets/js/179.69276272.js"><link rel="prefetch" href="/assets/js/18.f3ac24f5.js"><link rel="prefetch" href="/assets/js/180.a0c58c29.js"><link rel="prefetch" href="/assets/js/181.57bad9aa.js"><link rel="prefetch" href="/assets/js/182.71631dbb.js"><link rel="prefetch" href="/assets/js/183.36700795.js"><link rel="prefetch" href="/assets/js/184.5ee457e1.js"><link rel="prefetch" href="/assets/js/185.dab26dc0.js"><link rel="prefetch" href="/assets/js/186.62182fb6.js"><link rel="prefetch" href="/assets/js/187.90f68294.js"><link rel="prefetch" href="/assets/js/188.47c27a34.js"><link rel="prefetch" href="/assets/js/189.43e8281f.js"><link rel="prefetch" href="/assets/js/19.1db9316d.js"><link rel="prefetch" href="/assets/js/190.cb84aa8a.js"><link rel="prefetch" href="/assets/js/191.37fee735.js"><link rel="prefetch" href="/assets/js/192.c3b52852.js"><link rel="prefetch" href="/assets/js/193.6dde8403.js"><link rel="prefetch" href="/assets/js/194.2f6cc7b4.js"><link rel="prefetch" href="/assets/js/195.e184ddd4.js"><link rel="prefetch" href="/assets/js/196.9b52d5ca.js"><link rel="prefetch" href="/assets/js/197.06981a33.js"><link rel="prefetch" href="/assets/js/198.df0f9384.js"><link rel="prefetch" href="/assets/js/199.67944962.js"><link rel="prefetch" href="/assets/js/20.12397a15.js"><link rel="prefetch" href="/assets/js/200.4501595e.js"><link rel="prefetch" href="/assets/js/201.7bf3c484.js"><link rel="prefetch" href="/assets/js/202.78672ba7.js"><link rel="prefetch" href="/assets/js/203.94a17595.js"><link rel="prefetch" href="/assets/js/204.57caf7ea.js"><link rel="prefetch" href="/assets/js/205.275f09c6.js"><link rel="prefetch" href="/assets/js/206.910c502a.js"><link rel="prefetch" href="/assets/js/207.25ba76b1.js"><link rel="prefetch" href="/assets/js/208.ac0ce057.js"><link rel="prefetch" href="/assets/js/209.22fd98e0.js"><link rel="prefetch" href="/assets/js/21.0904e92c.js"><link rel="prefetch" href="/assets/js/210.7c8f5a93.js"><link rel="prefetch" href="/assets/js/211.7f9c3a69.js"><link rel="prefetch" href="/assets/js/212.fd617dc1.js"><link rel="prefetch" href="/assets/js/213.6fbe9440.js"><link rel="prefetch" href="/assets/js/214.bd38fd68.js"><link rel="prefetch" href="/assets/js/215.6abe6351.js"><link rel="prefetch" href="/assets/js/216.5ff50ee8.js"><link rel="prefetch" href="/assets/js/217.0a27cbf1.js"><link rel="prefetch" href="/assets/js/218.100ed227.js"><link rel="prefetch" href="/assets/js/219.91e6c412.js"><link rel="prefetch" href="/assets/js/22.443d5a8d.js"><link rel="prefetch" href="/assets/js/220.fbf36889.js"><link rel="prefetch" href="/assets/js/221.58c1e9fa.js"><link rel="prefetch" href="/assets/js/222.71a0fc30.js"><link rel="prefetch" href="/assets/js/223.267a54ce.js"><link rel="prefetch" href="/assets/js/224.cc579cb2.js"><link rel="prefetch" href="/assets/js/225.01845f8f.js"><link rel="prefetch" href="/assets/js/226.62e4b538.js"><link rel="prefetch" href="/assets/js/227.cfd1ba4f.js"><link rel="prefetch" href="/assets/js/228.77708580.js"><link rel="prefetch" href="/assets/js/229.320d7ec2.js"><link rel="prefetch" href="/assets/js/23.07e7ca32.js"><link rel="prefetch" href="/assets/js/230.cb4d08a9.js"><link rel="prefetch" href="/assets/js/231.799e2a17.js"><link rel="prefetch" href="/assets/js/232.1c3484ee.js"><link rel="prefetch" href="/assets/js/233.dce055b2.js"><link rel="prefetch" href="/assets/js/234.556f0f91.js"><link rel="prefetch" href="/assets/js/235.789e12cf.js"><link rel="prefetch" href="/assets/js/236.843a2b3c.js"><link rel="prefetch" href="/assets/js/237.16074ae9.js"><link rel="prefetch" href="/assets/js/238.ea41b51d.js"><link rel="prefetch" href="/assets/js/239.c08ab8cd.js"><link rel="prefetch" href="/assets/js/24.47775858.js"><link rel="prefetch" href="/assets/js/240.402437af.js"><link rel="prefetch" href="/assets/js/241.35af0e0f.js"><link rel="prefetch" href="/assets/js/242.63e3b11f.js"><link rel="prefetch" href="/assets/js/243.69b762fd.js"><link rel="prefetch" href="/assets/js/244.56391794.js"><link rel="prefetch" href="/assets/js/245.d5236618.js"><link rel="prefetch" href="/assets/js/246.19f88db6.js"><link rel="prefetch" href="/assets/js/247.877ff1af.js"><link rel="prefetch" href="/assets/js/248.b2e03c40.js"><link rel="prefetch" href="/assets/js/249.1622b100.js"><link rel="prefetch" href="/assets/js/25.081e4a20.js"><link rel="prefetch" href="/assets/js/250.cb777c9f.js"><link rel="prefetch" href="/assets/js/251.1a20cc7d.js"><link rel="prefetch" href="/assets/js/252.ed924fe0.js"><link rel="prefetch" href="/assets/js/253.e590646c.js"><link rel="prefetch" href="/assets/js/254.1422532c.js"><link rel="prefetch" href="/assets/js/255.55c9dc35.js"><link rel="prefetch" href="/assets/js/256.4d31804d.js"><link rel="prefetch" href="/assets/js/257.ebabcc54.js"><link rel="prefetch" href="/assets/js/258.b22846eb.js"><link rel="prefetch" href="/assets/js/259.042948a4.js"><link rel="prefetch" href="/assets/js/26.b386d831.js"><link rel="prefetch" href="/assets/js/260.fcc14c93.js"><link rel="prefetch" href="/assets/js/261.68448547.js"><link rel="prefetch" href="/assets/js/262.0562278e.js"><link rel="prefetch" href="/assets/js/263.bc9da9d4.js"><link rel="prefetch" href="/assets/js/264.2b87e530.js"><link rel="prefetch" href="/assets/js/265.c15b85e0.js"><link rel="prefetch" href="/assets/js/266.b92fa576.js"><link rel="prefetch" href="/assets/js/267.0d123c28.js"><link rel="prefetch" href="/assets/js/268.51153093.js"><link rel="prefetch" href="/assets/js/269.32ccae2e.js"><link rel="prefetch" href="/assets/js/27.c1442227.js"><link rel="prefetch" href="/assets/js/270.34569486.js"><link rel="prefetch" href="/assets/js/271.3a78116a.js"><link rel="prefetch" href="/assets/js/272.674abdec.js"><link rel="prefetch" href="/assets/js/273.d483a2d3.js"><link rel="prefetch" href="/assets/js/274.e0ed8b61.js"><link rel="prefetch" href="/assets/js/275.46f50c22.js"><link rel="prefetch" href="/assets/js/276.eb671083.js"><link rel="prefetch" href="/assets/js/277.fd35a81a.js"><link rel="prefetch" href="/assets/js/28.8a7f62c8.js"><link rel="prefetch" href="/assets/js/29.5f9cd7ee.js"><link rel="prefetch" href="/assets/js/3.71f6ef69.js"><link rel="prefetch" href="/assets/js/30.7967c9e6.js"><link rel="prefetch" href="/assets/js/31.f55a5b8f.js"><link rel="prefetch" href="/assets/js/32.cc9499cd.js"><link rel="prefetch" href="/assets/js/33.334a61a3.js"><link rel="prefetch" href="/assets/js/34.ef3aebf4.js"><link rel="prefetch" href="/assets/js/35.414bd3c4.js"><link rel="prefetch" href="/assets/js/36.d2bdef4f.js"><link rel="prefetch" href="/assets/js/37.e2d9d196.js"><link rel="prefetch" href="/assets/js/38.da85938a.js"><link rel="prefetch" href="/assets/js/39.647eba06.js"><link rel="prefetch" href="/assets/js/4.f79dde20.js"><link rel="prefetch" href="/assets/js/40.4b990977.js"><link rel="prefetch" href="/assets/js/41.21b0f134.js"><link rel="prefetch" href="/assets/js/42.fdfaa916.js"><link rel="prefetch" href="/assets/js/43.5b289d9c.js"><link rel="prefetch" href="/assets/js/44.5e879161.js"><link rel="prefetch" href="/assets/js/45.b17f20fa.js"><link rel="prefetch" href="/assets/js/46.e6499f7c.js"><link rel="prefetch" href="/assets/js/47.974887a7.js"><link rel="prefetch" href="/assets/js/48.a36e700b.js"><link rel="prefetch" href="/assets/js/49.331cfd03.js"><link rel="prefetch" href="/assets/js/50.5e975249.js"><link rel="prefetch" href="/assets/js/51.1b732661.js"><link rel="prefetch" href="/assets/js/52.4eef0576.js"><link rel="prefetch" href="/assets/js/53.d18c8dfe.js"><link rel="prefetch" href="/assets/js/54.cbe5e4a4.js"><link rel="prefetch" href="/assets/js/55.8fece5f1.js"><link rel="prefetch" href="/assets/js/56.47bf9afb.js"><link rel="prefetch" href="/assets/js/57.c29d5068.js"><link rel="prefetch" href="/assets/js/58.a20f0410.js"><link rel="prefetch" href="/assets/js/59.ea81fa07.js"><link rel="prefetch" href="/assets/js/6.eb074153.js"><link rel="prefetch" href="/assets/js/60.3723df7f.js"><link rel="prefetch" href="/assets/js/61.155cca8d.js"><link rel="prefetch" href="/assets/js/62.8da8ea65.js"><link rel="prefetch" href="/assets/js/63.5bd79ce0.js"><link rel="prefetch" href="/assets/js/64.a5ca2219.js"><link rel="prefetch" href="/assets/js/65.495ff5d7.js"><link rel="prefetch" href="/assets/js/66.6eb434da.js"><link rel="prefetch" href="/assets/js/67.b239e11f.js"><link rel="prefetch" href="/assets/js/68.2f0e4d2b.js"><link rel="prefetch" href="/assets/js/69.df762d95.js"><link rel="prefetch" href="/assets/js/7.40294d1f.js"><link rel="prefetch" href="/assets/js/70.28266a81.js"><link rel="prefetch" href="/assets/js/71.d0ba6102.js"><link rel="prefetch" href="/assets/js/72.b4506afa.js"><link rel="prefetch" href="/assets/js/73.a102f988.js"><link rel="prefetch" href="/assets/js/74.b65ceb71.js"><link rel="prefetch" href="/assets/js/75.8775c057.js"><link rel="prefetch" href="/assets/js/76.a4bbfbee.js"><link rel="prefetch" href="/assets/js/77.6d2ff50a.js"><link rel="prefetch" href="/assets/js/78.8cbe9520.js"><link rel="prefetch" href="/assets/js/79.615a535c.js"><link rel="prefetch" href="/assets/js/8.e19f41a7.js"><link rel="prefetch" href="/assets/js/80.d4bbb3aa.js"><link rel="prefetch" href="/assets/js/81.975f86f1.js"><link rel="prefetch" href="/assets/js/82.afe6c57f.js"><link rel="prefetch" href="/assets/js/83.ae50cd27.js"><link rel="prefetch" href="/assets/js/84.86238e0e.js"><link rel="prefetch" href="/assets/js/85.2b93078d.js"><link rel="prefetch" href="/assets/js/86.68abb63e.js"><link rel="prefetch" href="/assets/js/87.c09110ef.js"><link rel="prefetch" href="/assets/js/88.1c13c54d.js"><link rel="prefetch" href="/assets/js/89.3ba95f20.js"><link rel="prefetch" href="/assets/js/9.91501183.js"><link rel="prefetch" href="/assets/js/90.441809aa.js"><link rel="prefetch" href="/assets/js/91.8f403c17.js"><link rel="prefetch" href="/assets/js/92.578260e5.js"><link rel="prefetch" href="/assets/js/93.9f75fd85.js"><link rel="prefetch" href="/assets/js/94.f84ccf45.js"><link rel="prefetch" href="/assets/js/95.debc753b.js"><link rel="prefetch" href="/assets/js/96.b713f83f.js"><link rel="prefetch" href="/assets/js/97.b1793154.js"><link rel="prefetch" href="/assets/js/98.c5d5fcab.js"><link rel="prefetch" href="/assets/js/99.57270090.js">
    <link rel="stylesheet" href="/assets/css/0.styles.d732307f.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/img/logo.png" alt="Kehao's blog" class="logo"> <span class="site-name can-hide">Kehao's blog</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="编程学习" class="dropdown-title"><a href="/" class="link-title router-link-active">编程学习</a> <span class="title" style="display:none;">编程学习</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>教程网站</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://www.runoob.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  菜鸟教程
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://javaguide.cn/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Java Guide
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://pdai.tech/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Java全栈知识体系
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://learngitbranching.js.org/?locale=zh_CN" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GIT在线学习
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li><li class="dropdown-item"><h4>工具类网站</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://d.serctl.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github release加速下载
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://www.bejson.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  BE JSON
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://tool.lu/markdown/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Markdown在线编辑器
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="笔记" class="dropdown-title"><a href="/" class="link-title router-link-active">笔记</a> <span class="title" style="display:none;">笔记</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/ds/" class="nav-link">数据结构与算法</a></li><li class="dropdown-item"><!----> <a href="/python/" class="nav-link">python</a></li><li class="dropdown-item"><!----> <a href="/safe/" class="nav-link">安全</a></li><li class="dropdown-item"><!----> <a href="/java/" class="nav-link">java</a></li><li class="dropdown-item"><!----> <a href="/system/" class="nav-link">操作系统</a></li><li class="dropdown-item"><!----> <a href="/network/" class="nav-link">网络</a></li><li class="dropdown-item"><!----> <a href="/cryptography/" class="nav-link">密码学</a></li><li class="dropdown-item"><!----> <a href="/software_use/" class="nav-link">软件使用</a></li><li class="dropdown-item"><!----> <a href="/teacher/" class="nav-link">教师资格证</a></li><li class="dropdown-item"><!----> <a href="/database/" class="nav-link">数据库</a></li><li class="dropdown-item"><!----> <a href="/mq/" class="nav-link">消息队列</a></li><li class="dropdown-item"><!----> <a href="/microservice/" class="nav-link">微服务</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="生活学习" class="dropdown-title"><a href="/" class="link-title router-link-active">生活学习</a> <span class="title" style="display:none;">生活学习</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>视频资源网站</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://c.wxbxkx.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  百度网盘视频资源
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://www.agemys.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  AGE动漫网
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li><li class="dropdown-item"><h4>烹饪学习</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://cook.aiurs.co/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  程序员做饭指南
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div><div class="nav-item"><a href="/collection/" class="nav-link">收藏</a></div><div class="nav-item"><a href="/about/" class="nav-link">关于</a></div> <a href="https://github.com//chenkehao1998" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><div class="blogger"><img src="/img/avatar.jfif"> <div class="blogger-info"><h3>Kehao Chen</h3> <span>冲冲冲！</span></div></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="编程学习" class="dropdown-title"><a href="/" class="link-title router-link-active">编程学习</a> <span class="title" style="display:none;">编程学习</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>教程网站</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://www.runoob.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  菜鸟教程
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://javaguide.cn/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Java Guide
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://pdai.tech/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Java全栈知识体系
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://learngitbranching.js.org/?locale=zh_CN" target="_blank" rel="noopener noreferrer" class="nav-link external">
  GIT在线学习
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li><li class="dropdown-item"><h4>工具类网站</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://d.serctl.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github release加速下载
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://www.bejson.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  BE JSON
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://tool.lu/markdown/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Markdown在线编辑器
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="笔记" class="dropdown-title"><a href="/" class="link-title router-link-active">笔记</a> <span class="title" style="display:none;">笔记</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/ds/" class="nav-link">数据结构与算法</a></li><li class="dropdown-item"><!----> <a href="/python/" class="nav-link">python</a></li><li class="dropdown-item"><!----> <a href="/safe/" class="nav-link">安全</a></li><li class="dropdown-item"><!----> <a href="/java/" class="nav-link">java</a></li><li class="dropdown-item"><!----> <a href="/system/" class="nav-link">操作系统</a></li><li class="dropdown-item"><!----> <a href="/network/" class="nav-link">网络</a></li><li class="dropdown-item"><!----> <a href="/cryptography/" class="nav-link">密码学</a></li><li class="dropdown-item"><!----> <a href="/software_use/" class="nav-link">软件使用</a></li><li class="dropdown-item"><!----> <a href="/teacher/" class="nav-link">教师资格证</a></li><li class="dropdown-item"><!----> <a href="/database/" class="nav-link">数据库</a></li><li class="dropdown-item"><!----> <a href="/mq/" class="nav-link">消息队列</a></li><li class="dropdown-item"><!----> <a href="/microservice/" class="nav-link">微服务</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="生活学习" class="dropdown-title"><a href="/" class="link-title router-link-active">生活学习</a> <span class="title" style="display:none;">生活学习</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>视频资源网站</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://c.wxbxkx.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  百度网盘视频资源
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-subitem"><a href="https://www.agemys.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  AGE动漫网
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li><li class="dropdown-item"><h4>烹饪学习</h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="https://cook.aiurs.co/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  程序员做饭指南
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div><div class="nav-item"><a href="/collection/" class="nav-link">收藏</a></div><div class="nav-item"><a href="/about/" class="nav-link">关于</a></div> <a href="https://github.com//chenkehao1998" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>基础</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>集合</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>多线程</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>spring</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>jvm</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/pages/e78c12/" class="sidebar-link">垃圾收集器_</a></li><li><a href="/pages/ecc12f/" class="sidebar-link">内存屏障</a></li><li><a href="/pages/f0e774/" class="sidebar-link">浅析java中的TLAB</a></li><li><a href="/pages/7844f9/" class="sidebar-link">为啥加锁可以解决可见性问题呢？</a></li><li><a href="/pages/53d695/" class="sidebar-link">主内存和工作内存的关系</a></li><li><a href="/pages/f4ef8d/" class="sidebar-link">jackson中@JsonProperty、@JsonIgnore等常用注解总结</a></li><li><a href="/pages/8f8483/" class="sidebar-link">Java OOM问题如何排查</a></li><li><a href="/pages/bff2a8/" class="sidebar-link">java对象头</a></li><li><a href="/pages/1b51c8/" class="sidebar-link">Java内存模型(JMM)</a></li><li><a href="/pages/4be2cf/" class="sidebar-link">java强引用、弱引用、软引用、虚引用</a></li><li><a href="/pages/a6fc4c/" class="sidebar-link">JMM：Java内存模型</a></li><li><a href="/pages/016c1e/" aria-current="page" class="active sidebar-link">JVM内存结构</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header level2"><a href="/pages/016c1e/#_2-1-局部变量表" class="sidebar-link">2.1 局部变量表</a></li><li class="sidebar-sub-header level2"><a href="/pages/016c1e/#_2-2-操作数栈" class="sidebar-link">2.2 操作数栈</a></li></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span> 解决问题</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper "><div class="articleInfo-wrap" data-v-1baff76c><div class="articleInfo" data-v-1baff76c><ul class="breadcrumbs" data-v-1baff76c><li data-v-1baff76c><a href="/" title="首页" class="iconfont icon-home router-link-active" data-v-1baff76c></a></li> <li data-v-1baff76c><a href="/categories/?category=java" title="分类" data-v-1baff76c>java</a></li><li data-v-1baff76c><a href="/categories/?category=jvm" title="分类" data-v-1baff76c>jvm</a></li></ul> <div class="info" data-v-1baff76c><div title="作者" class="author iconfont icon-touxiang" data-v-1baff76c><a href="https://github.com/chenkehao1998" target="_blank" title="作者" class="beLink" data-v-1baff76c>kehao</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-1baff76c><a href="javascript:;" data-v-1baff76c>2022-04-17</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-title">目录</div> <div class="right-menu-content"></div></div></div> <h1><img src="">JVM内存结构<!----></h1> <!----> <div class="theme-vdoing-content content__default"><p>Java 虚拟机在执行 Java 程序的过程中会把它管理的内存划分为若干个不同的数据区域。每个区域都有各自的作用。</p> <p>分析 JVM 内存结构，主要就是分析 JVM 运行时数据存储区域。JVM 的运行时数据区主要包括：<strong>堆、栈、方法区、程序计数器</strong>等。而 JVM 的优化问题主要在<strong>线程共享的数据区</strong>中：<strong>堆、方法区</strong>。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_43f8e9b1b3214c209.bf6fe98f.png" alt=""></p> <h1 id="_1-程序计数器"><a href="#_1-程序计数器" class="header-anchor">#</a> 1. 程序计数器</h1> <p><strong>程序计数器（Program Counter Register）<strong>是一块较小的内存空间，可以看作是</strong>当前线程</strong>所执行字节码的<strong>行号指示器</strong>，指向下一个将要执行的指令代码，由执行引擎来读取下一条指令。更确切的说，<strong>一个线程的执行，是通过字节码解释器改变当前线程的计数器的值，来获取下一条需要执行的字节码指令，从而确保线程的正确执行</strong>。</p> <p>为了确保线程切换后（<strong>上下文切换</strong>）能恢复到正确的执行位置，<strong>每个线程都有一个独立的程序计数器</strong>，各个线程的计数器互不影响，独立存储。也就是说程序计数器是<strong>线程私有的内存</strong>。</p> <p>如果线程执行 Java 方法，这个计数器记录的是正在执行的虚拟机字节码指令的地址；如果执行的是 Native 方法，计数器值为Undefined。</p> <p><strong>程序计数器不会发生内存溢出（OutOfMemoryError即OOM）问题。</strong></p> <h1 id="_2-栈"><a href="#_2-栈" class="header-anchor">#</a> 2. 栈</h1> <p>JVM 中的栈包括 <strong>Java 虚拟机栈</strong>和本地方法栈，两者的<strong>区别</strong>就是，Java 虚拟机栈为 JVM 执行 Java 方法服务，本地方法栈则为 JVM 使用到的 Native 方法服务。两者作用是极其相似的，本文主要介绍 Java 虚拟机栈，以下简称栈。</p> <blockquote><p><strong>Native 方法是什么？</strong></p></blockquote> <p>JDK 中有很多方法是使用 Native 修饰的。Native 方法<strong>不是以 Java 语言实现</strong>的，而是以本地语言实现的（比如 C 或 C++）。个人理解Native 方法是与操作系统直接交互的。比如通知垃圾收集器进行垃圾回收的代码 System.gc()，就是使用 native 修饰的。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token keyword">class</span> <span class="token class-name">System</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">Runtime</span><span class="token punctuation">.</span><span class="token function">getRuntime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
 
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Runtime</span> <span class="token punctuation">{</span>
    <span class="token comment">//使用native修饰</span>
     <span class="token keyword">public</span> <span class="token keyword">native</span> <span class="token keyword">void</span> <span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><blockquote><p><strong>什么是栈？</strong></p></blockquote> <p><strong>定义：限定仅在表头进行插入和删除操作的线性表</strong>。即<strong>压栈（入栈）和弹栈（出栈）<strong>都是对</strong>栈顶元素</strong>进行操作的。所以栈是<strong>后进先出</strong>的。</p> <p>栈是<strong>线程私有</strong>的，他的生命周期与线程相同。每个线程都会分配一个栈的空间，即<strong>每个线程拥有独立的栈空间</strong>。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_24c9346d9dc745908.37711f9e.png" alt=""></p> <blockquote><p><strong>栈中存储的是什么？</strong></p></blockquote> <p><strong>栈帧</strong>是栈的元素。<strong>每个方法在执行时都会创建一个栈帧</strong>。栈帧中存储了<strong>局部变量表、操作数栈、动态连接和方法出口</strong>等信息。每个方法从调用到运行结束的过程，就对应着一个栈帧在栈中压栈到出栈的过程。</p> <p><img src="/assets/img/20190409182042686_b5ce7e1b75424e7880a35e0a1d049371.9fffb258.png" alt=""></p> <h2 id="_2-1-局部变量表"><a href="#_2-1-局部变量表" class="header-anchor">#</a> 2.1 局部变量表</h2> <p>栈帧中，由一个<strong>局部变量表存储数据</strong>。局部变量表中存储了<strong>基本数据类型</strong>（boolean、byte、char、short、int、float、long、double）的<strong>局部变量（包括参数）、和对象的引用（String、数组、对象等），但是不存储对象的内容</strong>。局部变量表所需的内存空间在<strong>编译期间完成分配</strong>，在方法运行期间不会改变局部变量表的大小。</p> <p>局部变量的容量以**变量槽（Variable Slot）**为最小单位，每个变量槽最大存储32位的数据类型。对于64位的数据类型（long、double），JVM 会为其分配两个连续的变量槽来存储。以下简称 Slot 。</p> <p>JVM 通过索引定位的方式使用局部变量表，索引的范围从0开始至局部变量表中最大的 Slot 数量。<strong>普通方法与 static 方法</strong>在第 0 个槽位的存储有所不同。非 static 方法的第 0 个槽位存储方法所属对象实例的引用。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_62ea324825d943088.3989b9aa.png" alt=""></p> <blockquote><p><strong>Slot 复用？</strong></p></blockquote> <p>为了尽可能的节省栈帧空间，局部变量表中的 <strong>Slot 是可以复用</strong>的。方法中定义的局部变量，其作用域不一定会覆盖整个方法。当方法运行时，如果已经<strong>超出了某个变量的作用域</strong>，即变量失效了，那这个变量对应的 Slot 就可以交给其他变量使用，也就是所谓的 <strong>Slot 复用</strong>。通过一个例子来理解变量“失效”。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token keyword">boolean</span> flag<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>flag<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">int</span> a <span class="token operator">=</span> <span class="token number">66</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    
    <span class="token keyword">int</span> b <span class="token operator">=</span> <span class="token number">55</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>当虚拟机运行 test 方法，就会创建一个栈帧，并压入到当前线程的栈中。当运行到 int a = 66时，在当前栈帧的局部变量中创建一个 Slot 存储变量 a，当运行到 int b = 55时，此时已经超出变量 a 的作用域了（变量 a 的作用域在{}所包含的代码块中），此时 a 就失效了，变量a 占用的 Slot 就可以交给b来使用，这就是 Slot 复用。</p> <p>凡事有利弊。Slot 复用虽然节省了栈帧空间，但是会伴随一些额外的<strong>副作用</strong>。比如，Slot 的复用会直接影响到系统的垃圾收集行为。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TestDemo</span> <span class="token punctuation">{</span>
 
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        
        <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> placeholder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token number">64</span> <span class="token operator">*</span> <span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">1024</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>上段代码很简单，先向内存中填充了 64M 的数据，然后通知虚拟机进行垃圾回收。为了更清晰的查看垃圾回收的过程，我们再虚拟机的运行参数中加上“<strong>-verbose:gc</strong>”,这个参数的作用就是<strong>打印 GC 信息</strong>。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_44df04bb06814e2cb.b2ac4a99.png" alt=""></p> <p>打印的GC信息如下：</p> <p><img src="/assets/img/20190410185953669_8cf9fca04f9542eb8454de058bd882bf.7a8c9b19.png" alt=""></p> <p>可以看到虚拟机没有回收这 64M 内存。为什么没有被回收？其实很好理解，当执行 System.gc() 方法时，变量 placeholder 还在作用域范围之内，虚拟机是不会回收的，它还是“有效”的。</p> <p>我们对上面的代码稍作修改，使其作用域“失效”。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TestDemo</span> <span class="token punctuation">{</span>
 
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> placeholder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token number">64</span> <span class="token operator">*</span> <span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">1024</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p>当运行到 System.gc() 方法时，变量 placeholder 的作用域已经失效了。它已经“无用”了，虚拟机会回收它所占用的内存了吧？</p> <p>运行结果：</p> <p><img src="/assets/img/20190410190827875_f2a1b45b16124313b0557cdc49f0a7cc.c0c47f04.png" alt=""></p> <p>发现虚拟机还是没有回收 placeholder 变量占用的 64M 内存。为什么所想非所见呢？在解释之前，我们再对代码稍作修改。在System.gc()方法执行之前，加入一个局部变量。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TestDemo</span> <span class="token punctuation">{</span>
 
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token punctuation">{</span>
            <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token punctuation">]</span> placeholder <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token keyword">byte</span><span class="token punctuation">[</span><span class="token number">64</span> <span class="token operator">*</span> <span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">1024</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">int</span> a <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">gc</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>在 System.gc() 方法之前，加入 int a = 0，再执行方法，查看垃圾回收情况。</p> <p><img src="/assets/img/20190410191854837_209bca271bd942d89cc1addfa6751313.806ee64a.png" alt=""></p> <p>发现 placeholder 变量占用的64M内存空间被回收了，如果不理解局部变量表的Slot复用，很难理解这种现象的。</p> <p>而 <strong>placeholder 变量能否被回收的关键</strong>就在于：局部变量表中的 Slot 是否还存有关于 placeholder 对象的引用。</p> <p>第一次修改中，限定了 placeholder 的作用域，但<strong>之后并没有任何对局部变量表的读写操作</strong>，placeholder 变量在局部变量表中占用的Slot没有被其它变量所复用，所以作为 GC Roots 一部分的局部变量表仍然保持着对它的关联。所以 placeholder 变量没有被回收。</p> <p>第二次修改后，运行到 int a = 0 时，已经超过了 placeholder 变量的作用域，此时 placeholder 在局部变量表中占用的Slot可以交给其他变量使用。<strong>而变量a正好复用了 placeholder 占用的 Slot</strong>，至此局部变量表中的 Slot 已经没有 placeholder 的引用了，虚拟机就回收了placeholder 占用的 64M 内存空间。</p> <hr> <h2 id="_2-2-操作数栈"><a href="#_2-2-操作数栈" class="header-anchor">#</a> 2.2 操作数栈</h2> <p><strong>操作数栈</strong>是一个<strong>后进先出</strong>栈。操作数栈的<strong>元素可以是任意的Java数据类型</strong>。方法刚开始执行时，操作数栈是<strong>空的</strong>，在方法执行过程中，通过字节码指令对操作数栈进行<strong>压栈和出栈</strong>的操作。<strong>通常进行<strong><strong>算数运算</strong></strong>的时候是通过操作数栈来进行的</strong>**，<strong><strong>又或者是在调用其他方法的时候通过操作数栈进行</strong></strong>参数传递****。操作数栈可以理解为栈帧中用于<strong><strong>计算</strong></strong>的临时数据存储区**。</p> <p>通过一段代码来了解操作数栈。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">OperandStack</span><span class="token punctuation">{</span>
 
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">int</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">int</span> a<span class="token punctuation">,</span> <span class="token keyword">int</span> b<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">int</span> c <span class="token operator">=</span> a <span class="token operator">+</span> b<span class="token punctuation">;</span>
        <span class="token keyword">return</span> c<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
 
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token function">add</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">,</span> <span class="token number">98</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>使用 javap **反编译 **OperandStack 后，根据虚拟机指令集，得出操作数栈的运行流程如下：</p> <p><img src="" alt=""></p> <p>add 方法刚开始执行时，操作数栈是空的。当执行 iload_0 时，把局部变量 0 压栈，即 100 入操作数栈。然后执行 iload_1，把局部变量1压栈，即 98 入操作数栈。接着执行 iadd，弹出两个变量（100 和 98 出操作数栈），对 100 和 98 进行求和，然后将结果 198 压栈。然后执行 istore_2，弹出结果（出栈）。</p> <p>下面通过一张图，对比执行100+98操作，<strong>局部变量表和操作数栈的变化情况</strong>。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_5e15bd3473b44920a.10129206.jpg" alt=""></p> <blockquote><p><strong>栈中可能出现哪些异常？</strong></p></blockquote> <p><strong>StackOverflowError：栈溢出错误</strong></p> <p>如果一个线程在计算时所需要用到栈大小 &gt; 配置允许最大的栈大小，那么Java虚拟机将抛出 StackOverflowError</p> <p><strong>OutOfMemoryError：内存不足</strong></p> <p>栈进行动态扩展时如果无法申请到足够内存，会抛出 OutOfMemoryError 异常。</p> <blockquote><p><strong>如何设置栈参数？</strong></p></blockquote> <p>使用 <strong>-Xss <strong>设置栈大小，通常几百K就够用了。由于栈是</strong>线程私有</strong>的，<strong>线程数越多，占用栈空间越大</strong>。</p> <p><strong>栈决定了函数调用的深度</strong>。这也是慎用递归调用的原因。递归调用时，每次调用方法都会创建栈帧并压栈。当调用一定次数之后，所需栈的大小已经超过了虚拟机运行配置的最大栈参数，就会抛出 StackOverflowError 异常。</p> <h1 id="_3-java堆"><a href="#_3-java堆" class="header-anchor">#</a> 3. Java堆</h1> <p>堆是Java虚拟机所管理的内存中最大的一块存储区域。堆内存被所有<strong>线程共享</strong>。主要存放使用<strong>new</strong>关键字创建的对象。所有<strong>对象实例以及数组</strong>都要在堆上分配。垃圾收集器就是根据GC算法，收集堆上<strong>对象所占用的内存空间（收集的是对象占用的空间而不是对象本身）</strong>。</p> <p>Java堆分为<strong>年轻代</strong>（Young Generation）和<strong>老年代</strong>（Old Generation）；<strong>年轻代又分为伊甸园（Eden）和幸存区（Survivor区）；幸存区又分为From Survivor空间和 To Survivor空间。</strong></p> <p>年轻代存储“新生对象”，我们新创建的对象存储在年轻代中。当年轻内存占满后，会触发<strong>Minor GC</strong>，清理年轻代内存空间。</p> <p>老年代存储<strong>长期存活的对象和大对象</strong>。年轻代中存储的对象，经过多次GC后仍然存活的对象会移动到老年代中进行存储。老年代空间占满后，会触发<strong>Full GC</strong>。</p> <p><strong>注：Full GC</strong>是清理整个堆空间，包括年轻代和老年代。如果Full GC之后，堆中仍然无法存储对象，就会抛出<strong>OutOfMemoryError</strong>异常。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_bb62ebd0575c40a1b.a085124f.png" alt=""></p> <blockquote><p>Java堆设置常用参数</p></blockquote> <table><thead><tr><th>参数</th> <th>描述</th></tr></thead> <tbody><tr><td>-Xms</td> <td>堆内存初始大小</td></tr> <tr><td>-Xmx（MaxHeapSize）</td> <td>堆内存最大允许大小，一般不要大于物理内存的80%</td></tr> <tr><td>-XX:NewSize（-Xns）</td> <td>年轻代内存初始大小</td></tr> <tr><td>-XX:MaxNewSize（-Xmn）</td> <td>年轻代内存最大允许大小，也可以缩写</td></tr> <tr><td>-XX:NewRatio</td> <td>新生代和老年代的比值<br><br>值为4 表示 新生代:老年代=1:4，即年轻代占堆的1/5</td></tr> <tr><td>-XX:SurvivorRatio=8</td> <td>年轻代中Eden区与Survivor区的容量比例值，默认为8<br><br>表示两个Survivor :eden=2:8，即一个Survivor占年轻代的1/10</td></tr> <tr><td>-XX:+HeapDumpOnOutOfMemoryError</td> <td>内存溢出时，导出堆信息到文件</td></tr> <tr><td>-XX:+HeapDumpPath</td> <td>堆Dump路径<br><br>-Xmx20m -Xms5m<br><br>-XX:+HeapDumpOnOutOfMemoryError<br><br>-XX:HeapDumpPath=d:/a.dump</td></tr> <tr><td>-XX:OnOutOfMemoryError</td> <td>当发生OOM内存溢出时，执行一个脚本<br><br>-XX:OnOutOfMemoryError=D:/tools/jdk1.7_40/bin/printstack.bat %p<br><br>%p表示线程的id pid</td></tr> <tr><td>-XX:MaxTenuringThreshold=7</td> <td>表示如果在幸存区移动多少次没有被垃圾回收，进入老年代</td></tr></tbody></table> <h1 id="_4-方法区-method-area"><a href="#_4-方法区-method-area" class="header-anchor">#</a> 4. 方法区（Method Area）</h1> <p>方法区同 Java 堆一样是被所有<strong>线程共享</strong>的区间，用于存储<strong>已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码</strong>。更具体的说，静态变量+常量+类信息（版本、方法、字段等）+运行时常量池存在方法区中。<strong>常量池是方法区的一部分</strong>。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_72726c982b8f459db.396ff092.png" alt=""></p> <p><strong>注</strong>：JDK1.8 使用元空间 **MetaSpace **替代方法区，元空间并不在 JVM中，而是使用本地内存。元空间两个参数：</p> <ol><li>MetaSpaceSize：初始化元空间大小，控制发生GC阈值</li> <li>MaxMetaspaceSize ： 限制元空间大小上限，防止异常占用过多物理内存</li></ol> <p>常量池中存储编译器生成的各种<strong>字面量和符号引用</strong>。字面量就是Java中常量的意思。比如文本字符串，final修饰的常量等。方法引用则包括类和接口的全限定名，方法名和描述符，字段名和描述符等。</p> <p><img src="/assets/img/watermark_type_ZmFuZ3poZW5naGVpd_a925c58d493d4ec69.505b1d93.png" alt=""></p> <blockquote><p><strong>常量池有什么用 ？</strong></p></blockquote> <p>**优点：**常量池避免了频繁的创建和销毁对象而影响系统性能，其实现了对象的共享。</p> <p>举个栗子： Integer 常量池（缓存池），和字符串常量池</p> <blockquote><p><strong>Integer常量池：</strong></p></blockquote> <p>我们知道 <strong>== 基本数据类型比较的是数值，而引用数据类型比较的是内存地址</strong>。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token class-name">TestIntegerCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        
        <span class="token class-name">Integer</span> i1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span><span class="token number">66</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Integer</span> i2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">integer</span><span class="token punctuation">(</span><span class="token number">66</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">Integer</span> i3 <span class="token operator">=</span> <span class="token number">66</span><span class="token punctuation">;</span>
        <span class="token class-name">Integer</span> i4 <span class="token operator">=</span> <span class="token number">66</span><span class="token punctuation">;</span>
        <span class="token class-name">Integer</span> i5 <span class="token operator">=</span> <span class="token number">150</span><span class="token punctuation">;</span>
        <span class="token class-name">Integer</span> i6 <span class="token operator">=</span> <span class="token number">150</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>i1 <span class="token operator">==</span> i2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//false</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>i3 <span class="token operator">==</span> i4<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>i5 <span class="token operator">==</span> i6<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//false</span>
    <span class="token punctuation">}</span>
    
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>i1 和 i2 使用 new 关键字，每 new 一次都会在堆上创建一个对象，所以 i1 == i2 为 false。</p> <p>i3 == i4 为什么是 true 呢？Integer i3 = 66 实际上有一步<strong>装箱</strong>的操作，即将 int 型的 66 装箱成 Integer，通过 Integer 的 valueOf 方法。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">Integer</span> <span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token keyword">int</span> i<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">&gt;=</span> <span class="token class-name">IntegerCache</span><span class="token punctuation">.</span>low <span class="token operator">&amp;&amp;</span> i <span class="token operator">&lt;=</span> <span class="token class-name">IntegerCache</span><span class="token punctuation">.</span>high<span class="token punctuation">)</span><span class="token punctuation">{</span>
    	<span class="token keyword">return</span> <span class="token class-name">IntegerCache</span><span class="token punctuation">.</span>cache<span class="token punctuation">[</span>i <span class="token operator">+</span> <span class="token punctuation">(</span><span class="token operator">-</span><span class="token class-name">IntegerCache</span><span class="token punctuation">.</span>low<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>Integer 的 valueOf 方法很简单，它判断变量是否在 **IntegerCache **的最小值（-128）和最大值（127）之间，如果在，则返回常量池中的内容，否则 new 一个 Integer 对象。</p> <p>而 **IntegerCache **是 <strong>Integer的静态内部类</strong>，作用就是将 [-128,127] 之间的数“缓存”在 IntegerCache 类的 cache 数组中，valueOf 方法就是调用常量池的 cache 数组，不过是将 i3、i4 <strong>变量引用指向常量池中，没有真正的创建对象</strong>。而new Integer(i)则是直接在堆中创建对象。</p> <p>IntegerCache 类中，包含一个构造方法，三个静态变量：low最小值、high最大值、和Integer数组，还有一个静态代码块。静态代码块的作用就是在 IntegerCache 类加载的时候，对high最大值以及 Integer 数组初始化。也就是说当 IntegerCache 类加载的时候，最大最小值，和 Integer 数组就已经初始化好了。这个 Integer 数组其实就是包含了 -128到127之间的所有值。</p> <blockquote><p><strong>IntegerCache 源码</strong></p></blockquote> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">IntegerCache</span> <span class="token punctuation">{</span>
        <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> low <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">128</span><span class="token punctuation">;</span><span class="token comment">//最小值</span>
        <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token keyword">int</span> high<span class="token punctuation">;</span><span class="token comment">//最大值</span>
        <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">Integer</span> cache<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//缓存数组</span>
 
        <span class="token comment">//私有化构造方法，不让别人创建它。单例模式的思想</span>
        <span class="token keyword">private</span> <span class="token class-name">IntegerCache</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
 
        <span class="token comment">//类加载的时候，执行静态代码块。作用是将-128到127之间的数缓冲在cache[]数组中</span>
        <span class="token keyword">static</span> <span class="token punctuation">{</span>
            <span class="token comment">// high value may be configured by property</span>
            <span class="token keyword">int</span> h <span class="token operator">=</span> <span class="token number">127</span><span class="token punctuation">;</span>
            <span class="token class-name">String</span> integerCacheHighPropValue <span class="token operator">=</span>
                sun<span class="token punctuation">.</span>misc<span class="token punctuation">.</span>VM<span class="token punctuation">.</span><span class="token function">getSavedProperty</span><span class="token punctuation">(</span><span class="token string">&quot;java.lang.Integer.IntegerCache.high&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span>integerCacheHighPropValue <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">try</span> <span class="token punctuation">{</span>
                    <span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token function">parseInt</span><span class="token punctuation">(</span>integerCacheHighPropValue<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    i <span class="token operator">=</span> <span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">max</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token number">127</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token comment">// Maximum array size is Integer.MAX_VALUE</span>
                    h <span class="token operator">=</span> <span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">min</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token class-name">Integer</span><span class="token punctuation">.</span>MAX_VALUE <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token operator">-</span>low<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span> <span class="token keyword">catch</span><span class="token punctuation">(</span> <span class="token class-name">NumberFormatException</span> nfe<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    <span class="token comment">// If the property cannot be parsed into an int, ignore it.</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
            high <span class="token operator">=</span> h<span class="token punctuation">;</span>
 
            cache <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">[</span><span class="token punctuation">(</span>high <span class="token operator">-</span> low<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token comment">//初始化cache数组，根据最大最小值确定</span>
            <span class="token keyword">int</span> j <span class="token operator">=</span> low<span class="token punctuation">;</span>
            <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> k <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> k <span class="token operator">&lt;</span> cache<span class="token punctuation">.</span>length<span class="token punctuation">;</span> k<span class="token operator">++</span><span class="token punctuation">)</span><span class="token comment">//遍历将数据放入cache数组中</span>
                cache<span class="token punctuation">[</span>k<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span>j<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
 
            <span class="token comment">// range [-128, 127] must be interned (JLS7 5.1.7)</span>
            <span class="token keyword">assert</span> <span class="token class-name">IntegerCache</span><span class="token punctuation">.</span>high <span class="token operator">&gt;=</span> <span class="token number">127</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
 
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br></div></div><p>而 i5 == i6 为 false，就是因为 **150 不在 Integer 常量池的最大最小值之间【-128,127】，从而 new 了一个对象，**所以为 false。</p> <p>再看一段<strong>拆箱</strong>的代码。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
       <span class="token class-name">Integer</span> i1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token class-name">Integer</span> i2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span><span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token class-name">Integer</span> i3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Integer</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>i3 <span class="token operator">==</span> i1<span class="token operator">+</span>i2<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>由于 i1 和 i2 是 Integer 对象，是不能使用+运算符的。首先 i1 和 i2 进行<strong>自动拆箱</strong>操作，拆箱成int后再进行数值加法运算。i3 也是拆箱后再与之比较数值是否相等的。所以 i3 == i1+i2 其实是比较的 int 型数值是否相等，所以为true。</p> <hr> <blockquote><p><strong>String常量池：</strong></p></blockquote> <p><strong>String 是由 final 修饰的类，是不可以被继承的</strong>。通常有两种方式来创建对象。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">String</span> str <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">&quot;abcd&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">String</span> str <span class="token operator">=</span> <span class="token string">&quot;abcd&quot;</span><span class="token punctuation">;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>第一种使用 new 创建的对象，存放在堆中。每次调用都会创建一个新的对象。</p> <p>第二种先在栈上创建一个 String 类的对象引用变量 str，然后通过符号引用去字符串常量池中找有没有 “abcd”，如果没有，则将“abcd”存放到字符串常量池中，并将栈上的 str 变量引用指向常量池中的“abcd”。如果常量池中已经有“abcd”了，则不会再常量池中创建“abcd”，而是直接将 str 引用指向常量池中的“abcd”。</p> <p>对于 String 类，equals 方法用于比较字符串内容是否相同； == 号用于比较内存地址是否相同，即是否指向同一个对象。通过代码验证上面理论。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">&quot;abcd&quot;</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">&quot;abcd&quot;</span><span class="token punctuation">;</span>
	<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>str1 <span class="token operator">==</span> str2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
    


</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>首先在栈上存放变量引用 str1，然后通过符号引用去常量池中找是否有 abcd，没有，则将 abcd 存储在常量池中，然后将 str1 指向常量池的 abcd。当创建 str2 对象，去常量池中发现已经有 abcd 了，就将 str2 引用直接指向 abcd 。所以str1 == str2，指向<strong>同一个内存地址</strong>。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
    <span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">&quot;abcd&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">String</span><span class="token punctuation">(</span><span class="token string">&quot;abcd&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>str1 <span class="token operator">==</span> str2<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>str1 和 str2 使用 new 创建对象，分别在堆上创建了不同的对象。两个引用指向堆中两个不同的对象，所以为 false。</p> <blockquote><p><strong>关于字符串 + 号连接问题：</strong></p></blockquote> <p>对于字符串常量的 + 号连接，在程序编译期，JVM就会将其优化为 + 号连接后的值。所以在<strong>编译期其字符串常量的值就确定了</strong>。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token class-name">String</span> a <span class="token operator">=</span> <span class="token string">&quot;a1&quot;</span><span class="token punctuation">;</span>   
<span class="token class-name">String</span> b <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>   
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//result = true  </span>
 
<span class="token class-name">String</span> a <span class="token operator">=</span> <span class="token string">&quot;atrue&quot;</span><span class="token punctuation">;</span>   
<span class="token class-name">String</span> b <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span> <span class="token operator">+</span> <span class="token string">&quot;true&quot;</span><span class="token punctuation">;</span>   
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//result = true </span>
 
<span class="token class-name">String</span> a <span class="token operator">=</span> <span class="token string">&quot;a3.4&quot;</span><span class="token punctuation">;</span>   
<span class="token class-name">String</span> b <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span> <span class="token operator">+</span> <span class="token number">3.4</span><span class="token punctuation">;</span>   
<span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token punctuation">(</span>a <span class="token operator">==</span> b<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//result = true </span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><blockquote><p><strong>关于字符串引用 + 号连接问题：</strong></p></blockquote> <p>对于字符串<strong>引用</strong>的 + 号连接问题，由于字符串引用在<strong>编译期是无法确定</strong>下来的，在程序的<strong>运行期动态分配并创建新的地址存储对象</strong>。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
       <span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">;</span>
	   <span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">&quot;ab&quot;</span><span class="token punctuation">;</span>
	   <span class="token class-name">String</span> str3 <span class="token operator">=</span> str1 <span class="token operator">+</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">;</span>
	   <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>str2 <span class="token operator">==</span> str3<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//false</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>对于上边代码，str3 等于 str1 引用 + 字符串常量“b”，在编译期无法确定，在运行期动态的分配并将连接后的新地址赋给 str3，所以 str2 和 str3 引用的内存地址不同，所以 str2 == str3 结果为 false</p> <p>通过 jad 反编译工具，分析上述代码到底做了什么。编译指令如下：</p> <p><img src="" alt=""></p> <p>经过 jad 反编译工具反编译代码后，代码如下</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">TestDemo</span>
<span class="token punctuation">{</span>
 
    <span class="token keyword">public</span> <span class="token class-name">TestDemo</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>
 
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span> args<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token class-name">String</span> s <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s1 <span class="token operator">=</span> <span class="token string">&quot;ab&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s2 <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span>s<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;b&quot;</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>s1 <span class="token operator">=</span> s2<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><p>发现 <strong>new 了一个 StringBuilder 对象，然后使用 append 方法优化了 + 操作符</strong>。new 在堆上创建对象，而 String s1=“ab”则是在常量池中创建对象，两个应用所指向的内存地址是不同的，所以 s1 == s2 结果为 false。</p> <p><strong>注</strong>：我们已经知道了字符串引用的 + 号连接问题，其实是在运行期间创建一个 StringBuilder 对象，使用其 append 方法将字符串连接起来。这个也是我们开发中需要注意的一个问题，就是<strong>尽量不要在 for 循环中使用 + 号来操作字符串</strong>。看下面一段代码：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">String</span> s <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            s <span class="token operator">=</span> s <span class="token operator">+</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>在 for 循环中使用 + 连接字符串，<strong>每循环一次，就会新建 StringBuilder 对象，append 后就“抛弃”了它</strong>。如果我们在循环外创建StringBuilder 对象，然后在循环中使用 append 方法追加字符串，就可以<strong>节省 n-1 次创建和销毁对象的时间</strong>。所以在循环中连接字符串，一般使用 StringBuilder 或者 StringBuffer，而不是使用 + 号操作。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">StringBuilder</span> s <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StringBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">100</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            s<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">&quot;a&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><blockquote><p><strong>使用final修饰的字符串</strong></p></blockquote> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">final</span> <span class="token class-name">String</span> str1 <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> str2 <span class="token operator">=</span> <span class="token string">&quot;ab&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> str3 <span class="token operator">=</span> str1 <span class="token operator">+</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>str2 <span class="token operator">==</span> str3<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>final 修饰的变量是一个常量，编译期就能确定其值。所以 str1 + &quot;b&quot;就等同于 &quot;a&quot; + &quot;b&quot;，所以结果是 true。</p> <blockquote><p><strong>String对象的intern方法。</strong></p></blockquote> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">String</span> s <span class="token operator">=</span> <span class="token string">&quot;ab&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s1 <span class="token operator">=</span> <span class="token string">&quot;a&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s2 <span class="token operator">=</span> <span class="token string">&quot;b&quot;</span><span class="token punctuation">;</span>
        <span class="token class-name">String</span> s3 <span class="token operator">=</span> s1 <span class="token operator">+</span> s2<span class="token punctuation">;</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s3 <span class="token operator">==</span> s<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//false</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>s3<span class="token punctuation">.</span><span class="token function">intern</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> s<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>通过前面学习我们知道，s1+s2 实际上在堆上 new 了一个 StringBuilder 对象，而 s 在常量池中创建对象 “ab”，所以 s3 == s 为 false。但是 s3 调用 <strong>intern 方法，返回的是s3的内容（ab）在常量池中的地址值</strong>。所以 s3.intern() == s 结果为 true。</p></div></div> <!----> <div class="page-edit"><!----> <!----> <div class="last-updated"><span class="prefix">上次更新:</span> <span class="time">2022/04/18, 00:47:23</span></div></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/pages/a6fc4c/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">JMM：Java内存模型</div></a> <a href="/pages/05cd74/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">Maven创建module弹出被忽略(Ignored)的Ignored—pom.xml文件解决办法</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/pages/a6fc4c/" class="prev">JMM：Java内存模型</a></span> <span class="next"><a href="/pages/05cd74/">Maven创建module弹出被忽略(Ignored)的Ignored—pom.xml文件解决办法</a>→
      </span></p></div></div></div> <div class="article-list"><div class="article-title"><a href="/archives/" class="iconfont icon-bi">最近更新</a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><a href="/pages/ea7864/"><div>
            git 回滚 reset、revert
            <!----></div></a> <span class="date">04-27</span></dt></dl><dl><dd>02</dd> <dt><a href="/pages/a306d5/"><div>
            Mysql 8.0 安装压缩版教程
            <!----></div></a> <span class="date">04-27</span></dt></dl><dl><dd>03</dd> <dt><a href="/pages/3622a0/"><div>
            阿里开发规范解读：为啥禁用外键约束
            <!----></div></a> <span class="date">04-27</span></dt></dl> <dl><dd></dd> <dt><a href="/archives/" class="more">更多文章&gt;</a></dt></dl></div></div></main></div> <div class="footer"><div class="icons"><a href="mailto:chenkehaockh@foxmail.com" title="发邮件" target="_blank" class="iconfont icon-youjian"></a><a href="https://github.com/chenkehao1998" title="GitHub" target="_blank" class="iconfont icon-github"></a><a href="https://music.163.com/#/user/home?id=39714521" title="听音乐" target="_blank" class="iconfont icon-erji"></a></div> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2022-2022
    <span></span></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div> <div title="主题模式" class="button blur theme-mode-but iconfont icon-zhuti"><ul class="select-box" style="display:none;"><li class="iconfont icon-zidong">
          跟随系统
        </li><li class="iconfont icon-rijianmoshi">
          浅色模式
        </li><li class="iconfont icon-yejianmoshi">
          深色模式
        </li><li class="iconfont icon-yuedu">
          阅读模式
        </li></ul></div></div> <!----> <!----> <!----></div><div class="global-ui"><div></div></div></div>
    <script src="/assets/js/app.28ae8733.js" defer></script><script src="/assets/js/2.89335391.js" defer></script><script src="/assets/js/5.0ce40fe9.js" defer></script>
  </body>
</html>
